#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavutil/avutil.h>
#include <libswscale/swscale.h>
#include <libavutil/pixdesc.h>


#include "soapH.h"
#include "wsaapi.h"
#include "wsseapi.h"
#include "wsdd.nsmap"

#include "onvif_comm.h"
#include "onvif_dump.h"


/************************************************************************
**函数：open_rtsp
**功能：从RTSP获取音视频流数据
**参数：
        [in]  rtsp - RTSP地址
**返回：无
************************************************************************/
void open_rtsp(char* rtsp)
{
    unsigned int    i;
    int             ret;
    int             video_st_index = -1;
    int             audio_st_index = -1;
    AVFormatContext* ifmt_ctx = NULL;
    AVPacket        pkt;
    AVStream*        st = NULL;
    char            errbuf[64];
    
    av_register_all();                                                          // Register all codecs and formats so that they can be used.
    avformat_network_init();                                                    // Initialization of network components

    if ((ret = avformat_open_input(&ifmt_ctx, rtsp, 0, NULL)) < 0)              // Open the input file for reading.
    {
        printf("Could not open input file '%s' (error '%s')\n", rtsp, av_make_error_string(errbuf, sizeof(errbuf), ret));
        goto EXIT;
    }

    if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0)                  // Get information on the input file (number of streams etc.).
    {
        printf("Could not open find stream info (error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
        goto EXIT;
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++)                                  // dump information
    {
        av_dump_format(ifmt_ctx, i, rtsp, 0);
    }

    for (i = 0; i < ifmt_ctx->nb_streams; i++)                                  // find video stream index
    {
        st = ifmt_ctx->streams[i];

        switch(st->codec->codec_type)
        {
            case AVMEDIA_TYPE_AUDIO:
                audio_st_index = i;
                break;

            case AVMEDIA_TYPE_VIDEO:
                video_st_index = i;
                break;

            default:
                break;
        }
    }

    if (-1 == video_st_index)
    {
        printf("No H.264 video stream in the input file\n");
        goto EXIT;
    }

    av_init_packet(&pkt);                                                       // initialize packet.
    pkt.data = NULL;
    pkt.size = 0;

    while (1)
    {
        do
        {
            ret = av_read_frame(ifmt_ctx, &pkt);                                // read frames
        }
        while (ret == AVERROR(EAGAIN));

        if (ret < 0)
        {
            printf("Could not read frame (error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
            break;
        }

        if (pkt.stream_index == video_st_index)                                 // video frame
        {
            printf("Video Packet size = %d\n", pkt.size);
        }
        else if(pkt.stream_index == audio_st_index)                             // audio frame
        {
            printf("Audio Packet size = %d\n", pkt.size);
        }
        else
        {
            printf("Unknow Packet size = %d\n", pkt.size);
        }

        av_packet_unref(&pkt);
    }

EXIT:

    if (NULL != ifmt_ctx)
    {
        avformat_close_input(&ifmt_ctx);
        ifmt_ctx = NULL;
    }

    return ;
}

void cb_discovery(char* DeviceXAddr)
{
    int ret;
    int profile_cnt = 0;                                                        // 设备配置文件个数
    struct tagProfile* profiles = NULL;                                         // 设备配置文件列表
    struct tagCapabilities capa;                                                // 设备能力信息
    char uri[ONVIF_ADDRESS_SIZE] = {0};                                         // 不带认证信息的URI地址
    char uri_auth[ONVIF_ADDRESS_SIZE + 50] = {0};                               // 带有认证信息的URI地址
    ret = ONVIF_GetDeviceInformation(DeviceXAddr);

    if (0 == ret)
    {
        ONVIF_GetCapabilities(DeviceXAddr, &capa);
        profile_cnt = ONVIF_GetProfiles(capa.MediaXAddr, &profiles);                // 获取媒体配置信息（主/辅码流配置信息）

        if (profile_cnt > 0)
        {
            ONVIF_GetStreamUri(capa.MediaXAddr, profiles[0].token, uri, sizeof(uri)); // 获取RTSP地址
            make_uri_withauth(uri, USERNAME, PASSWORD, uri_auth, sizeof(uri_auth)); // 生成带认证信息的URI（有的IPC要求认证）
            //open_rtsp(uri_auth);                                                    // 读取主码流的音视频数据
        }

        if (NULL != profiles)
        {
            free(profiles);
            profiles = NULL;
        }
    }
}

int main(int argc, char** argv)
{
    ONVIF_DetectDevice(cb_discovery);
    return 0;
}
